﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;

using SpectrEngine.Framework;
using SpectrEngine.Framework.Input;
using CellWarzGame.Collections;

using CellWarzGame.Screens;
using SpectrEngine.Framework.Collision;
using CellWarzGame.Actors;

namespace CellWarzGame.Actors
{
    class Virus : Cell
    {
        const float MinForce = 0.0001f;
        const float MoveForce = 0.005f;

        CellType mimicState;
        TimeSpan mimicTimeLeft;

        List<SoundEffect> killSounds;
        List<SoundEffect> attackSounds;
        
        bool attacking;

        Random rand = new Random();

        protected float linearDamping;
        public float LinearDamping
        {
            get
            {
                return linearDamping;
            }
            set
            {
                linearDamping = value;
            }
        }

        protected Vector2 directionalForce;
        public Vector2 DirectionalForce
        {
            get
            {
                return directionalForce;
            }
            set
            {
                directionalForce = value;
            }
        }

        public override void Dispose()
        {
            base.Dispose();
            new GameOverScreen(Game);
            Game.Services.GetService<ScreenManager>().RemoveScreen(0);

        }


        protected override void InitCollision()
        {
            hitZones = new BoundingCircle[1];
            hitZones[0] = new BoundingCircle(Vector2.Zero, 100.0f);

            attackZones = new BoundingCircle[1];
            attackZones[0] = new BoundingCircle(new Vector2(25,0), 75.0f);

            bounds = new BoundingRect(75.0f, 75.0f);
        }


        public Virus(Game game, Side _side, Controler _controler, Vector2 position, CellType _cellType) :
            base(game, _side, _controler, position, _cellType)
        {
            actionState = ActionState.Chase;
            mimicTimeLeft = TimeSpan.FromMilliseconds(0);
            mimicState = CellType.Virus;
            attacking = false;
            InitPhysics();
            LoadSounds();
        }

        private void InitPhysics()
        {
            LinearDamping = 0.001f;
            directionalForce = new Vector2(0, 0);
        }

        private void LoadSounds()
        {
            killSounds = new List<SoundEffect>();
            killSounds.Add(Game.Content.Load<SoundEffect>("Sounds\\burp"));
            killSounds.Add(Game.Content.Load<SoundEffect>("Sounds\\piggy"));
            killSounds.Add(Game.Content.Load<SoundEffect>("Sounds\\pop"));
            killSounds.Add(Game.Content.Load<SoundEffect>("Sounds\\slap"));
            killSounds.Add(Game.Content.Load<SoundEffect>("Sounds\\Death1"));
            killSounds.Add(Game.Content.Load<SoundEffect>("Sounds\\Death2"));

            attackSounds = new List<SoundEffect>();
            attackSounds.Add(Game.Content.Load<SoundEffect>("Sounds\\Attack1"));
            attackSounds.Add(Game.Content.Load<SoundEffect>("Sounds\\Attack2"));
            attackSounds.Add(Game.Content.Load<SoundEffect>("Sounds\\Attack3"));
        }

        public override void Update(GameTime gameTime)
        {

            UpdateMimicState(gameTime);

            base.Update(gameTime);

        }

        private void UpdateMimicState(GameTime gameTime)
        {

            if (mimicTimeLeft.TotalSeconds > 0)
            {
                mimicTimeLeft -= gameTime.ElapsedGameTime;
            }
            else
            {
                mimicState = CellType.Virus;
                mimicTimeLeft = TimeSpan.FromSeconds(0);
                maxSpeed = 80;

            }
            //GamePadManager.IsButtonDown(PlayerIndex.One, GamePadButtons.A)
            if (GamePadManager.GetTrigger(PlayerIndex.One, GamePadTriggers.Left) > 0.75 ||
                GamePadManager.GetTrigger(PlayerIndex.One, GamePadTriggers.Right) > 0.75)
            {
                if (!attacking)
                {
                    attacking = true;
                    attackSounds[rand.Next(0, attackSounds.Count)].Play();
                }
                Action = ActionState.Attack;
            }
            else
            {
                if (actionState != ActionState.Death)
                {
                    attacking = false;
                    Action = ActionState.Chase;
                    maxSpeed = 80;
                }
            }
            
            if (GamePadManager.IsDPadPressed(PlayerIndex.One, GamePadDPads.Up))
            {
                mimicState = CellType.Skunk;
                mimicTimeLeft = TimeSpan.FromSeconds(5);
                maxSpeed = 80;

            }

            if (GamePadManager.IsDPadPressed(PlayerIndex.One, GamePadDPads.Left))
            {
                mimicState = CellType.Monk;
                mimicTimeLeft = TimeSpan.FromSeconds(5);
                maxSpeed = 80;

            }

            if (GamePadManager.IsDPadPressed(PlayerIndex.One, GamePadDPads.Right))
            {
                mimicState = CellType.Punk;
                mimicTimeLeft = TimeSpan.FromSeconds(5);                
                maxSpeed = 80;
            }

            if (GamePadManager.IsDPadPressed(PlayerIndex.One, GamePadDPads.Down))
            {
                mimicState = CellType.Virus;
                mimicTimeLeft = TimeSpan.FromSeconds(5);
                maxSpeed = 80;
            }

            if (GamePadManager.IsButtonPressed(PlayerIndex.One, GamePadButtons.A))
            {
                side = Side.green;
            }
            if (GamePadManager.IsButtonPressed(PlayerIndex.One, GamePadButtons.B))
            {
                side = Side.red;
            }
            if (GamePadManager.IsButtonPressed(PlayerIndex.One, GamePadButtons.X))
            {
                side = Side.blue;
            }
            if (GamePadManager.IsButtonPressed(PlayerIndex.One, GamePadButtons.Y))
            {
                side = Side.yellow;
            }

            switch (actionState)
            {
                case ActionState.Attack:
                    switch (mimicState)
                    {
                        case CellType.Monk:
                            currentSheet = 4;
                            break;

                        case CellType.Punk:
                            currentSheet = 6;
                            maxSpeed = 240.0f;
                            break;

                        case CellType.Skunk:
                            currentSheet = 8;
                            break;

                        case CellType.Virus:
                            currentSheet = 1;
                            break;
                    }
                    break;

                case ActionState.Death:
                    currentSheet = 2;  // update with death sheet
                    break;
                default:
                    switch (mimicState)
                    {
                        case CellType.Monk:
                            currentSheet = 3;
                            break;

                        case CellType.Punk:
                            currentSheet = 5;
                            break;

                        case CellType.Skunk:
                            currentSheet = 7;
                            break;

                        case CellType.Virus:
                            currentSheet = 0;
                            break;
                    }
                    break;
            }

        }

        protected override void InitSpriteSheets()
        {
            base.InitSpriteSheets();

            // virus 0-2
            spriteSheets.Add(Game.Content.Load<Texture2D>("Images\\VirusSheet"));
            spriteSheetRects.Add(GetSpriteSheetRects(spriteSheets[spriteSheets.Count - 1], 150, 150));
            spriteSheets.Add(Game.Content.Load<Texture2D>("Images\\VirusDefaultShortAttackSheet"));
            spriteSheetRects.Add(GetSpriteSheetRects(spriteSheets[spriteSheets.Count - 1], 400, 400));
            spriteSheets.Add(Game.Content.Load<Texture2D>("Images\\VirusDeathSheet"));
            spriteSheetRects.Add(GetSpriteSheetRects(spriteSheets[spriteSheets.Count - 1], 150, 150));

            // munk 3,4
            spriteSheets.Add(Game.Content.Load<Texture2D>("Images\\VirusMimicMunkIdleSheet"));
            spriteSheetRects.Add(GetSpriteSheetRects(spriteSheets[spriteSheets.Count - 1], 150, 150));
            spriteSheets.Add(Game.Content.Load<Texture2D>("Images\\VirusMimicMunkAttackSheet"));
            spriteSheetRects.Add(GetSpriteSheetRects(spriteSheets[spriteSheets.Count - 1], 400, 400));

            // punk 5,6
            spriteSheets.Add(Game.Content.Load<Texture2D>("Images\\VirusMimicPunkIdleSheet"));
            spriteSheetRects.Add(GetSpriteSheetRects(spriteSheets[spriteSheets.Count - 1], 150, 150));
            spriteSheets.Add(Game.Content.Load<Texture2D>("Images\\VirusMimicPunkAttackSheet"));
            spriteSheetRects.Add(GetSpriteSheetRects(spriteSheets[spriteSheets.Count - 1], 400, 400));

            // skunk 7,8
            spriteSheets.Add(Game.Content.Load<Texture2D>("Images\\VirusMimicSkunkIdleSheet"));
            spriteSheetRects.Add(GetSpriteSheetRects(spriteSheets[spriteSheets.Count - 1], 150, 150));
            spriteSheets.Add(Game.Content.Load<Texture2D>("Images\\VirusMimicSkunkAttackSheet"));
            spriteSheetRects.Add(GetSpriteSheetRects(spriteSheets[spriteSheets.Count - 1], 400, 400));

        }


        protected override void UpdateMovement(GameTime gameTime)
        {
            Vector2 v = GamePadManager.GetThumbstick(PlayerIndex.One, GamePadThumbSticks.Left);
            if (!((v.Y == 0) && (v.X == v.Y)))
            {
                v.Y *= -1;
                float a = AI.AI.AngleDiff(rotation, (float)Math.Atan2(v.Y, v.X));
                //v.Normalize();
                //Console.Out.WriteLine(v);
                ApplyForce(v, MoveForce);
                Rotate(a / 16);
            }
            Move(gameTime.ElapsedGameTime.Milliseconds);
        }

        protected override void SetActionState(ActionState actionStateParam)
        {
            base.SetActionState(actionStateParam);
        }

        public override void CollideWith(CollidableGameNode other)
        {
            base.CollideWith(other);

            if (other is Cell)
            {
                Cell enemy = (Cell)other;

                if (enemy.cellType != CellType.Tail)
                {
                    if (enemy.Action == ActionState.Attack)
                    {
                        hp--;

                        if (hp <= 0)
                        {
                            Action = ActionState.Death;
                        }
                    }

                    if (actionState == ActionState.Attack)
                    {
                        if (enemy.hp <= 0)
                        {
                            if (enemy.Action != ActionState.Death)
                            {
                                killSounds[rand.Next(0, killSounds.Count)].Play();

                                enemy.Action = ActionState.Death;
                            }
                        }
                        else
                        {
                            enemy.hp--;
                        }
                    }
                }
            }

        }


        public void ApplyForce(Vector2 dir, float force)
        {
            float a1 = (float)Math.Atan2(directionalForce.Y, directionalForce.X);
            float a2 = (float)Math.Atan2(dir.Y, dir.X);

            directionalForce.X = directionalForce.X + force * (float)Math.Cos(a2);
            directionalForce.Y = directionalForce.Y + force * (float)Math.Sin(a2);
        }

        private void Move(float time)
        {
            float x = 0;
            float y = 0;

            if (Math.Abs(directionalForce.X) > MinForce)
            {
                x = directionalForce.X * time;
                directionalForce.X -= directionalForce.X * linearDamping * time;
            }
            else
            {
                directionalForce.X = 0;
            }

            if (Math.Abs(directionalForce.Y) > MinForce)
            {
                y = directionalForce.Y * time;
                directionalForce.Y -= directionalForce.Y * linearDamping * time;
            }
            else
            {
                directionalForce.Y = 0;
            }

            if (x != 0 || y != 0)
            {
                Vector2 spot = new Vector2(x + Position.X, y + Position.Y);

                if (moveArea.Contains((int)spot.X, (int)spot.Y))
                {
                    Translate(new Vector2(x, y));
                }
                else
                {
                    if (spot.X > moveArea.Width)
                        spot.X -= moveArea.Width;
                    if (spot.Y > moveArea.Height)
                        spot.Y -= moveArea.Height;
                    if (spot.X < 0)
                        spot.X += moveArea.Width;
                    if (spot.Y < 0)
                        spot.Y += moveArea.Height;

                    Translate(new Vector2(spot.X - Position.X, spot.Y - Position.Y));
                }
            }
        }
    }
}
